home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / chaserog.zip / SRC_ROG.ZIP / chasecam.qc < prev    next >
Text File  |  1997-05-11  |  35KB  |  1,559 lines

  1. /*
  2. chasecam file
  3. player entity variables used:
  4. .dest_x,y,z  (HK WEAP)
  5. .dest1_x     (HUD)
  6. .dest1_y      (MSKIN PRO)
  7. .dest2_x,y,z  (CAM)
  8.  
  9.  #####################
  10.  ### chase cam mod ###
  11.  Rob Albin, 09 Sep 96
  12.  
  13.  orig functions modified:
  14.     WEAPONS.QC
  15.         W_SetCurrentAmmo
  16.         ImpulseCommands
  17.     CLIENT.QC
  18.         SetChangeParms
  19.         SetNewParms
  20.         DecodeLevelParms
  21.         PutClientInServer
  22.  
  23. // ref. defs.qc
  24.  
  25. // message protocol defines
  26. float SVC_SETVIEWPORT    = 5;
  27. float SVC_SETVIEWANGLES    = 10;
  28.  
  29. // free player entity variable
  30. // ('.float speed'  bit-flag defines:) changed:
  31. // player.dest2_x = bit-flag variable
  32. // player.dest2_y = chasecam distance
  33. // player.dest2_z = chasecam zmult (height offset)
  34. float HUD_ON          = 16;
  35. *float CHSCAM_MONSTER  = 8;* deleted *
  36. float CHSCAM_ON       = 4;
  37. float LASERTARG_LIT   = 2;
  38. float LASERTARG_ON    = 1;
  39. */
  40.  
  41. void( entity m_e, entity v_e) set_viewport =
  42. {
  43.     msg_entity = m_e;                         // target of message
  44.     WriteByte (MSG_ONE, SVC_SETVIEWPORT);
  45.     WriteEntity (MSG_ONE, v_e);           // view port
  46. };
  47.  
  48. void() Keep_cam_chasing_owner;
  49. void( float opt ) Remove_chase_cam;
  50.  
  51. // (moved to defs.qc)
  52. //float chasecam_dist = 118, chasecam_zmult = 0.30000;
  53. // changed to player.dest2_y (distance)
  54. // player.dest2_z (zmult)
  55. // set in client.qc for initial values
  56.  
  57. // Resets weapon model after changing view
  58. // called by chase cam or player entities
  59. void( entity player_ent ) Chase_cam_setweapon =
  60. {
  61.     local entity e;
  62.  
  63.     e = self;
  64.     self = player_ent;
  65.     if ( (self.dest2_x & CHSCAM_ON) ) self.weaponmodel = "";
  66.     else                            W_SetCurrentAmmo ();
  67.     self = e;
  68. };
  69.  
  70. // called either by player or chase cam entities (to restart)
  71. // vpos:
  72. // '0 0 0' = start from player
  73. // (else use as cam origin)
  74. void( entity cam_owner, vector vpos ) Start_chase_cam =
  75. {
  76.  
  77.     local entity    chase_cam;
  78.  
  79.     stuffcmd( cam_owner, "fov 80\n" );
  80.  
  81.     chase_cam = spawn();
  82.  
  83.     chase_cam.owner=cam_owner;
  84.  
  85.     // turn on bit-flag
  86.     chase_cam.owner.dest2_x = chase_cam.owner.dest2_x | CHSCAM_ON;
  87.  
  88.     chase_cam.solid = SOLID_NOT;
  89.     chase_cam.movetype = MOVETYPE_FLY;
  90.  
  91.  
  92.     chase_cam.angles = chase_cam.owner.angles;
  93.  
  94.     setmodel (chase_cam, "progs/eyes.mdl" );
  95.     setsize (chase_cam, '0 0 0', '0 0 0');
  96.  
  97.     if (vpos == '0 0 0')
  98.         setorigin( chase_cam, chase_cam.owner.origin + '0 0 22' );
  99.     else
  100.         setorigin( chase_cam, vpos );
  101.  
  102.     chase_cam.classname = "chase_cam";
  103.  
  104.     chase_cam.nextthink = time + 0.1;
  105.     chase_cam.think = Keep_cam_chasing_owner;
  106.  
  107.     // set CLOSE to 0 (ref. PlayerPreThink())
  108.     //chase_cam.owner.view_ofs_z = -1;
  109.     //set_viewport( cam_owner, chase_cam);
  110.     chase_cam.skin = 1; // let track function handle the remote view
  111.                               // part, start with "temp. disabled" flag set
  112.  
  113.     Chase_cam_setweapon( cam_owner );
  114.     // distance clipping
  115.     chase_cam.ammo_shells = cam_owner.dest2_y / 3;
  116.  
  117. };
  118.  
  119. // secondary think for cam entities
  120. void() Reable_chase_cam =
  121. {
  122.     self.nextthink = time + 0.1;
  123.  
  124.     //if (self.owner.health <= 0)
  125.     if (self.owner.solid == SOLID_NOT)
  126.     {
  127.         //owner died in water, reset .dest2_x flag for respawn
  128.         self.owner.dest2_x = self.owner.dest2_x | CHSCAM_ON;
  129.         remove( self );
  130.         return;
  131.     }
  132.  
  133.     if (self.owner.waterlevel)
  134.         return;
  135.  
  136.     self.owner.dest2_x = self.owner.dest2_x | CHSCAM_ON;
  137.     Chase_cam_setweapon( self.owner );
  138.  
  139.     self.skin = 1; // flag temp. disabled flag so track function
  140.                         // will reset remote view
  141.     self.solid = SOLID_NOT;
  142.     self.movetype = MOVETYPE_FLY;
  143.     setmodel (self, "progs/eyes.mdl" );
  144.     setsize (self, '0 0 0', '0 0 0');
  145.     setorigin( self, self.owner.origin);
  146.     self.ammo_shells = self.owner.dest2_y / 3; // distance clipping
  147.     self.think = Keep_cam_chasing_owner;
  148.     //Start_chase_cam( self.owner, '0 0 0' );
  149.     //remove( self );
  150.  
  151. };
  152.  
  153.  
  154. // called only by chase cam entities
  155. // opt values
  156. // TRUE = remove completely
  157. // FALSE = remove view but keep alive with Reable_chase_cam();
  158. void( float opt ) Remove_chase_cam =
  159. {
  160.     stuffcmd( self.owner, "fov 90\n" );
  161.  
  162.     // turn off bit-flag
  163.     self.owner.dest2_x = self.owner.dest2_x - (self.owner.dest2_x & CHSCAM_ON);
  164.  
  165.     // set view-point back to normal
  166.     set_viewport( self.owner, self.owner);
  167.  
  168.  
  169.     setmodel( self, "" );
  170.     self.velocity = '0 0 0';
  171.  
  172.     self.owner.view_ofs_z = 22;
  173.  
  174.     Chase_cam_setweapon( self.owner );
  175.  
  176.     if ( !opt )
  177.     {
  178.         self.nextthink = time + 0.1;
  179.         self.think = Reable_chase_cam;
  180.     }
  181.     else
  182.         remove( self );
  183.  
  184. };
  185.  
  186. void () cam_deathview =
  187. {
  188.     self.nextthink = time + 0.1;
  189.  
  190.     if (self.owner.solid != SOLID_NOT)
  191.     {
  192.         remove( self);
  193.         return;
  194.     }
  195.  
  196.     traceline( self.owner.origin, self.origin, TRUE, self.owner);
  197.     if (trace_inwater)
  198.     {
  199.         set_viewport( self.owner, self.owner);
  200.         self.owner.health = -1;
  201.         remove( self);
  202.         return;
  203.     }
  204.     if (trace_fraction < 1)
  205.     {
  206.         setorigin( self, trace_endpos - self.dest * 8);
  207.         self.velocity = '0 0 0';
  208.     }
  209.  
  210.     if (self.velocity != '0 0 0')
  211.     {
  212.         traceline( self.origin, self.origin + self.dest * 20, TRUE, self.owner);
  213.         if (trace_fraction < 1 || trace_inwater ||
  214.              vlen( self.origin - self.owner.origin) > 200)
  215.             self.velocity = '0 0 0';
  216.     }
  217.  
  218. };
  219.  
  220. // called only by player ents immediately after being killed, if
  221. // not already in chaseview, and not in water
  222. void() cam_startdeathview =
  223. {
  224.     local entity e;
  225.     local vector goal, ang;
  226.     ang = self.v_angle;
  227.     ang_x = 30; // pretend was a slight down aim
  228.     self.weaponmodel = "";
  229.  
  230.     e = spawn();
  231.     e.owner = self;
  232.     e.solid = SOLID_NOT;
  233.     e.movetype = MOVETYPE_FLY;
  234.     e.angles = e.owner.angles;
  235.     setmodel (e, "progs/eyes.mdl" );
  236.     setsize (e, '0 0 0', '0 0 0');
  237.  
  238.     makevectors( ang );
  239.     goal = (self.origin + '0 0 18') - (v_forward * 120);
  240.     traceline( self.origin + '0 0 18', goal, TRUE, self);
  241.     if (trace_inwater)
  242.     {
  243.         remove( e);
  244.         return;
  245.     }
  246.     setorigin( e, trace_endpos + (v_forward * 8));
  247.     e.velocity = '0 0 0' - v_forward * 20;
  248.     e.dest = '0 0 0' - v_forward; // save forward direction, used in cam_deathview
  249.     e.nextthink = time + 0.1;
  250.     e.think = cam_deathview;
  251.  
  252.     set_viewport( self, e);
  253.  
  254. };
  255.  
  256.  
  257. /*
  258.     main think function for cam entities
  259.         self.ammo_shells = distance clipping
  260.         self.ammo_nails = hang-up flag
  261.         self.dmg = lifts fix
  262.         self.frags = lifts fix
  263.         self.impulse = lifts fix
  264.         self.dest = deathview vector to save 'v_forward' of fade direction
  265.         self.skin = close proximity temporary disableing
  266.  
  267.     .v_angle_x:
  268.         78.8 (max down aim)
  269.         -68.9 (max up aim)
  270. */
  271. void() Keep_cam_chasing_owner =
  272. {
  273.     local vector vtmp1, vtmp2;
  274.     local vector owner_vec, goal, dir;
  275.     local float  dist, cap, f_f;
  276.     //debug var
  277.     //local string s;
  278.  
  279.  
  280.     self.nextthink = time + 0.1;
  281.  
  282.     // check if player toggled
  283.     if (! (self.owner.dest2_x & CHSCAM_ON))
  284.     {
  285.         Remove_chase_cam( TRUE );
  286.         return;
  287.     }
  288.  
  289.     if (self.owner.solid == SOLID_NOT)
  290.     {
  291.         stuffcmd( self.owner, "fov 90\n" );
  292.  
  293.         if (intermission_running)
  294.         {
  295.             set_viewport( self.owner, self.owner);
  296.             remove( self );
  297.         }
  298.         else
  299.         {  // deathview
  300.             self.velocity = '0 0 0' - normalize( self.owner.origin - self.origin) * 20;
  301.             self.angles = vectoangles( self.velocity);
  302.             makevectors( self.angles);
  303.             self.dest = v_forward; // save forward direction, used in cam_deathview
  304.             self.think = cam_deathview;
  305.             if (self.skin) // temp disable flag is set
  306.             {
  307.                 self.owner.view_ofs_z = -1;
  308.                 set_viewport( self.owner, self);
  309.             }
  310.         }
  311.         return;
  312.     }
  313.  
  314.  
  315.     if ( self.owner.waterlevel )
  316.     {
  317.         Remove_chase_cam( FALSE );
  318.         return;
  319.     }
  320.  
  321.     owner_vec = self.owner.origin + '0 0 22';
  322.  
  323.     // get player velocity relative to player's
  324.     // current yaw
  325.     // f_f (based on running calcs (maxspeed = 400)
  326.     //  (back ~= 640, forward ~= 0)
  327.     dir_y = self.owner.v_angle_y;
  328.     makevectors( dir );
  329.     f_f = vlen( (v_forward * 320) - self.owner.velocity );
  330.  
  331.     // held for use after second makevectors call for
  332.     // pulling forward on a down aim
  333.     dir = v_forward;
  334.  
  335. //   local string s;
  336. //   sprint( self.owner, "\n\n f_f = " );
  337. //   s = ftos( f_f );
  338. //   sprint( self.owner, s );
  339. //   sprint( self.owner, "\n f_r = " );
  340. //   s = ftos( f_r );
  341. //   sprint( self.owner, s );
  342. //   sprint( self.owner, "\n" );
  343.  
  344.     // increment fade-back variable
  345.     self.ammo_shells = self.ammo_shells + 4.5;
  346.     if (self.ammo_shells > self.owner.dest2_y)
  347.         self.ammo_shells = self.owner.dest2_y;
  348.  
  349.     makevectors( self.owner.v_angle );
  350.  
  351.     // set spot before clipping
  352.     //.v_angle_x:
  353.     //    78.8 (max down aim)
  354.     //    -68.9 (max up aim)
  355.  
  356.     goal = owner_vec - (v_forward * self.ammo_shells);
  357.     goal_z = goal_z + 14 + (self.ammo_shells * self.owner.dest2_z);
  358.  
  359.     // adjust initial goal
  360.     //////////////////////////////////////////////////
  361.     if (self.owner.v_angle_x > 0)
  362.     {
  363.         // pull forward
  364.         cap = self.owner.v_angle_x;
  365.         if (cap > 56) cap = 56;
  366.         goal = goal + dir * cap;
  367.  
  368.         // pull down
  369.         goal_z = goal_z - (self.owner.v_angle_x * (self.ammo_shells * 0.01));
  370.         cap = self.owner.origin_z + 28;
  371.         if (goal_z < cap)
  372.             goal_z = cap;
  373.     }
  374.  
  375.     // increase height if getting under the player
  376.     if (goal_z < owner_vec_z)
  377.     {
  378.         vtmp1 = goal; vtmp1_z = 0;
  379.         vtmp2 = owner_vec; vtmp2_z = 0;
  380.         cap = vlen( vtmp1 - vtmp2 );
  381.         if (cap < 100)
  382.         {
  383.             goal_z = goal_z + ((100 - cap) * 0.6);
  384.             if ( goal_z > owner_vec_z )
  385.                 goal_z = owner_vec_z;
  386.         }
  387.     }
  388.     //////////////////////////////////////
  389.  
  390.     // clip for brushes
  391.     //////////////////////////////////////
  392.     traceline (owner_vec, goal, FALSE, self.owner);
  393.     // pull a little forward, avoids most hang-ups along walls
  394.     goal = trace_endpos + ( v_forward * 2 );
  395.  
  396.     // clip fade-back variable
  397.     traceline( owner_vec, owner_vec - (v_forward * self.ammo_shells), FALSE, self.owner);
  398.     if (trace_fraction < 1)
  399.     {
  400.         self.ammo_shells = vlen(trace_endpos - owner_vec);
  401.         cap = fabs( self.owner.v_angle_x ) - 10;
  402.         if (cap > 0)
  403.             self.ammo_shells = self.ammo_shells + cap;
  404.     }
  405.  
  406.     traceline (self.origin, goal, FALSE, self.owner );
  407.     if (trace_fraction < 1)
  408.     {
  409.         // half it if blocked
  410.         dir = normalize(goal - owner_vec);
  411.         dist = vlen(goal - owner_vec) * 0.5;
  412.         goal =  owner_vec + dir * dist;
  413.     }
  414.  
  415.     // pad for floors and ceilings
  416.     traceline (goal, goal + '0 0 6', FALSE, self.owner );
  417.     if (trace_fraction < 1 ) goal = trace_endpos - '0 0 6';
  418.     else
  419.     {
  420.         traceline (goal, goal - '0 0 6', FALSE, self.owner );
  421.         if (trace_fraction < 1 ) goal = trace_endpos + '0 0 6';
  422.     }
  423.     ////////////////////////////////////////
  424.  
  425.     self.angles = self.owner.angles;
  426.  
  427.     traceline (self.origin, owner_vec, FALSE, self.owner );
  428.     if (trace_fraction < 1)
  429.     {
  430.         // vtmp1_z:  0 = LOS to head
  431.         //                -1 = LOS to feet, but not head
  432.         //                -2 = no LOS
  433.         traceline (self.origin, self.owner.origin - '0 0 24', FALSE, self.owner );
  434.         if (trace_fraction == 1)
  435.             vtmp1_z = -1;
  436.         else
  437.             vtmp1_z = -2;
  438.     }
  439.     else
  440.         vtmp1_z = 0;
  441.     if (vtmp1_z > -2)
  442.     {
  443.         dir = normalize(goal - self.origin);
  444.         dist = vlen(goal - self.origin);
  445.  
  446.         cap = dist * 0.16;
  447.  
  448.         if (cap > 5.2)
  449.             self.velocity = dir * dist * 5.2;
  450.         else if (cap > 1)
  451.             self.velocity = dir * dist * cap;
  452.         else
  453.             self.velocity = dir * dist;
  454.  
  455.         if (vtmp1_z == -1)
  456.         {
  457.             self.velocity_z = self.velocity_z - 400;
  458.         }
  459.  
  460.         // tighten up if owner running backwards
  461.         if (f_f > 560)
  462.         {
  463.             cap = self.velocity_z;
  464.             self.velocity = self.velocity * 2;
  465.             self.velocity_z = cap;
  466.         }
  467.  
  468.         if (! self.owner.velocity_z)
  469.         {
  470.             // rising/lowering lifts fix,
  471.             // quick and dirty hack, player.velocity_z stays at zero when
  472.             // moving on a lift, so check through an alternate route for the
  473.             // condition and amplify the current z velocity.
  474.             if (self.owner.origin_z != self.frags)
  475.                 //if (self.dmg &&  (self.owner.flags & FL_ONGROUND)) // avoid landing on ground events that can happen between thinks
  476.                     // wierd setup here with the .impulse var, forces a skip for first occurance,
  477.                     // avoids logic catching vel_z same/org_z dif. instance that happens when player
  478.                     // transitions between sloping to level ground while running, (also took care
  479.                     // of the same type of thing for landing after a jump)
  480.                     if (self.impulse)
  481.                         self.velocity_z = self.velocity_z * 3;
  482.                     else
  483.                         self.impulse = TRUE;
  484.         }
  485.         else if (self.impulse)
  486.             self.impulse = FALSE;
  487.  
  488.  
  489.  
  490.         // try to avoid hangups common to ceiling clips when player
  491.         // is running
  492.         if( self.oldorigin == self.origin )
  493.         {
  494.             if( dist > 16 )
  495.             {
  496.                 self.ammo_nails = self.ammo_nails + 1;
  497.                 if( self.ammo_nails > 2 )
  498.                 {
  499.                     self.ammo_nails = 0;
  500.                     self.velocity = '0 0 0';
  501.                     setorigin( self, goal );
  502.                 }
  503.             }
  504.             else
  505.                 self.ammo_nails = 0;
  506.         }
  507.     }
  508.     else
  509.     {
  510.         self.velocity = '0 0 0';
  511.         setorigin( self, goal );
  512.     }
  513.  
  514.     if (! self.skin) // .skin is 1 if in a temp disable state
  515.     {
  516.         if (vlen(self.owner.origin - self.origin) < 30)
  517.         {
  518.             self.skin = 1;
  519.             self.owner.view_ofs_z = 22;
  520.             set_viewport( self.owner, self.owner);
  521.         }
  522.     }
  523.     else
  524.     {
  525.         if (vlen(self.owner.origin - self.origin) > 39)
  526.         {
  527.             self.skin = 0;
  528.             self.owner.view_ofs_z = -1;
  529.             set_viewport( self.owner, self);
  530.         }
  531.     }
  532.  
  533.  
  534.     // hacks (only) section :-)
  535.  
  536.     // keep flag clear so internal C won't drop movement checks
  537.     if (self.flags & FL_ONGROUND)
  538.         self.flags = self.flags - FL_ONGROUND;
  539.  
  540.     self.oldorigin = self.origin; // cam hang-up hack
  541.     self.frags = self.owner.origin_z; // 'on lift' hack
  542.     self.dmg = self.owner.flags & FL_ONGROUND; // 'on lift' hack
  543. };
  544.  
  545.  
  546. // called by player only
  547. void() Toggle_chase_cam =
  548. {
  549.  
  550.     if (self.waterlevel)
  551.         return;
  552.  
  553.     if( (self.dest2_x & CHSCAM_ON) )
  554.     {
  555.         // will be noticed by next think
  556.         // of player's chase cam entity
  557.         self.dest2_x = self.dest2_x - CHSCAM_ON;
  558.     }
  559.     else
  560.         Start_chase_cam( self, '0 0 0' );
  561.  
  562. };
  563.  
  564. ////////////////////////////////////////////
  565. // laser targeter functions
  566.  
  567. // targeter ent. think function
  568. void() LaserTargeterTrack = {
  569.     local vector src;
  570.  
  571.     self.nextthink = time + 0.05;
  572.  
  573.     if (! (self.owner.dest2_x & LASERTARG_ON))
  574.     {
  575.         if( (self.owner.dest2_x & LASERTARG_LIT) )
  576.         {
  577.             self.owner.dest2_x = self.owner.dest2_x | LASERTARG_ON;
  578.             self.effects = self.effects | EF_DIMLIGHT;
  579.         }
  580.         else
  581.         {
  582.             remove( self );
  583.             return;
  584.         }
  585.     }
  586.  
  587.     if (self.owner.solid == SOLID_NOT)
  588.     {
  589.         // leave .dest2_x flags alone
  590.         remove( self );
  591.         return;
  592.     }
  593.  
  594.     if (self.owner.weapon == IT_AXE)
  595.     {
  596.         if (self.model != "")
  597.             setmodel( self, "" );
  598.     }
  599.     else if (self.model == "")
  600.         setmodel( self, "progs/cross1.mdl" );
  601.  
  602.     makevectors( self.owner.v_angle );
  603.     self.angles = vectoangles( v_forward );
  604.  
  605.     src = self.owner.origin + v_forward * 10;
  606.     src_z = self.owner.absmin_z + self.owner.size_z * 0.7;
  607.  
  608.     traceline( src,  src + v_forward * 2048, FALSE, self.owner);
  609.  
  610.     setorigin( self, (0.1 * src + 0.9 * trace_endpos) );
  611.  
  612.  
  613. };
  614.  
  615. void( entity targ_owner ) LaserTargeterToggle =
  616. {
  617.  
  618.     local entity e;
  619.  
  620.     if( (targ_owner.dest2_x & LASERTARG_ON) )
  621.     {
  622.         // don't activate glow in multi-player
  623.         if (! deathmatch  && ! coop)
  624.         {
  625.             if( (targ_owner.dest2_x & LASERTARG_LIT) )
  626.                 targ_owner.dest2_x = targ_owner.dest2_x - LASERTARG_LIT;
  627.             else
  628.                 targ_owner.dest2_x = targ_owner.dest2_x | LASERTARG_LIT;
  629.         }
  630.  
  631.         targ_owner.dest2_x = targ_owner.dest2_x - LASERTARG_ON;
  632.     }
  633.     else
  634.     {
  635.         targ_owner.dest2_x = targ_owner.dest2_x | LASERTARG_ON;
  636.  
  637.         e = spawn();
  638.         e.owner = targ_owner;
  639.  
  640.         e.movetype = MOVETYPE_NONE;
  641.         e.solid = SOLID_NOT;
  642.  
  643.         // setmodel( e, "progs/s_bubble.spr" );
  644.         setmodel( e, "progs/cross1.mdl" );
  645.         setsize( e, VEC_ORIGIN, VEC_ORIGIN );
  646.         setorigin( e, e.owner.origin );
  647.  
  648.         if( (e.owner.dest2_x & LASERTARG_LIT) )
  649.             e.effects = e.effects | EF_DIMLIGHT;
  650.  
  651.         e.nextthink = time + 0.1;
  652.         e.think = LaserTargeterTrack;
  653.  
  654.     }
  655.  
  656. };
  657. ////////////////////////////////////////////
  658.  
  659. void () Spawn_extra_changelevels;
  660. void() Chase_cam_lvlstart_think =
  661. {
  662.  
  663.     self.owner.skin = self.owner.dest1_y; //mskin pro stuff
  664.  
  665.     if ( (self.owner.dest2_x & CHSCAM_ON) )
  666.         Start_chase_cam( self.owner, '0 0 0' );
  667.  
  668.     if ( (self.owner.dest2_x & LASERTARG_ON) )
  669.     {
  670.         self.owner.dest2_x = self.owner.dest2_x - LASERTARG_ON;
  671.         LaserTargeterToggle( self.owner );
  672.     }
  673.  
  674.     if (world.model == "maps/start.bsp")
  675.         Spawn_extra_changelevels();
  676.  
  677.     remove( self );
  678. };
  679.  
  680.  
  681. // called in CLIENT.QC by void() PutClientInServer
  682. // player.dest2_x is set and saved between levels using parm16
  683. // in CLIENT.QC
  684. void() Chase_cam_level_start =
  685. {
  686.  
  687.     local entity e;
  688.  
  689.     e = spawn();
  690.     e.owner = self;
  691.     e.nextthink = time + 0.2;
  692.     e.think = Chase_cam_lvlstart_think;
  693.  
  694. };
  695.  
  696.  
  697. // opt:
  698. // 0 = minus
  699. // 1 = plus
  700. // 2 = read cvar temp1 for value
  701. // (player.dest2_y holds cam distance)
  702. void(float opt) Chase_cam_change_dist =
  703. {
  704.     local string s;
  705.  
  706.     if (!opt)
  707.     {
  708.         self.dest2_y = self.dest2_y - 2;
  709.         if (self.dest2_y < 10)
  710.             self.dest2_y = 10;
  711.     }
  712.     else if (opt == 1)
  713.         self.dest2_y = self.dest2_y + 2;
  714.     else
  715.         self.dest2_y = cvar( "temp1" );
  716.  
  717.     sprint( self, "chasecam distance = " );
  718.     s = ftos( self.dest2_y );
  719.     sprint( self, s );
  720.     sprint( self, "\n" );
  721.  
  722.  
  723. };
  724.  
  725. // opt:
  726. // 0 = minus
  727. // 1 = plus
  728. // 2 = read cvar temp1 for value
  729. // (player.dest2_z holds zmult)
  730. void(float opt) Chase_cam_change_zmult =
  731. {
  732.     local string str;
  733.     local float f;
  734.  
  735.     if (!opt)
  736.     {
  737.         self.dest2_z = self.dest2_z - 0.02;
  738.         if (self.dest2_z < 0)
  739.             self.dest2_z = 0;
  740.     }
  741.     else if (opt == 1)
  742.         self.dest2_z = self.dest2_z + 0.02;
  743.     else
  744.     {
  745.         f = cvar( "temp1" );
  746.         self.dest2_z = f * 0.01;
  747.     }
  748.  
  749.     sprint( self, "chasecam verticle offset = " );
  750.  
  751.     // convert and strip for display
  752.     // apparantly,
  753.     //    .dest2_z = .dest2_z +- 0.02;
  754.     // don't _exactly_ add/sub 0.02
  755.     f = self.dest2_z * 100;
  756.     f = rint( f );
  757.     str = ftos( f );
  758.  
  759.     sprint( self, str );
  760.     sprint( self, "\n" );
  761.  
  762.  
  763. };
  764.  
  765. /*
  766. Reads current values of cvar temp1:
  767. opt:
  768.     0 = into player.dest2_y (chasecam distance)
  769.     1 = into player.dest2_z (zmult)
  770. */
  771. void(float opt) Chase_cam_read_temp1 =
  772. {
  773.     if (!opt)
  774.         Chase_cam_change_dist(2);
  775.     else
  776.         Chase_cam_change_zmult(2);
  777. };
  778.  
  779. // ### chase cam mod ###
  780. // #####################
  781.  
  782. // ###############
  783. // ### HUD mod ###
  784.  
  785. /*
  786. player.dest1_x
  787.  
  788. to hold last player.health for automaticly printing health changes.
  789.  
  790.  Axe, Sh, D_brl, Nl, S_Nl, Grnd, Rckt, Ltng
  791. .armortype  (0.3, 0.6, 0.8)
  792. .armorvalue
  793. .currentammo
  794. .weapon
  795. */
  796.  
  797.  
  798. // opt:
  799. // 0 = print only health
  800. // 1 = print full status
  801. // called only by player in ImpulseCommands() and   W_WeaponFrame()
  802. void( float opt ) HUD_print_info =
  803. {
  804.     local string str;
  805.     local float cap, c, c2, c_inc;
  806.  
  807.     if (! (self.dest2_x & HUD_ON) ) return;
  808.  
  809.     if (opt == 1) // player selected full update
  810.     {
  811.         self.dest1_x = self.health;
  812.  
  813.         // ammo
  814.         c2 = 12;
  815.         if (self.ammo_shells1  > 9.5 ) c2 = c2 - 0.5;
  816.         if (self.ammo_shells1  > 99.5) c2 = c2 - 0.5;
  817.         if (self.ammo_nails1   > 9.5 ) c2 = c2 - 0.5;
  818.         if (self.ammo_nails1   > 99.5) c2 = c2 - 0.5;
  819.         if (self.ammo_rockets1 > 9.5 ) c2 = c2 - 0.5;
  820.         if (self.ammo_rockets1 > 99.5) c2 = c2 - 0.5;
  821.         if (self.ammo_cells1   > 9.5 ) c2 = c2 - 0.5;
  822.         if (self.ammo_cells1   > 99.5) c2 = c2 - 0.5;
  823.         if (self.ammo_lava_nails   > 9.5 ) c2 = c2 - 0.5;
  824.         if (self.ammo_lava_nails   > 99.5) c2 = c2 - 0.5;
  825.         if (self.ammo_multi_rockets   > 9.5 ) c2 = c2 - 0.5;
  826.         if (self.ammo_multi_rockets   > 99.5) c2 = c2 - 0.5;
  827.         if (self.ammo_plasma   > 9.5 ) c2 = c2 - 0.5;
  828.         if (self.ammo_plasma   > 99.5) c2 = c2 - 0.5;
  829.         c = 0;
  830.         while (c < c2) {sprint( self, " " ); c = c + 1;}
  831.  
  832.         str = ftos( self.ammo_shells1 );
  833.             sprint( self, str );
  834.             sprint( self, "Ä");
  835.         str = ftos( self.ammo_nails1 );
  836.             sprint( self, str );
  837.             sprint( self, "/");
  838.         str = ftos( self.ammo_lava_nails );
  839.             sprint( self, str );
  840.             sprint( self, "Ä");
  841.         str = ftos( self.ammo_rockets1 );
  842.             sprint( self, str );
  843.             sprint( self, "/");
  844.         str = ftos( self.ammo_multi_rockets );
  845.             sprint( self, str );
  846.             sprint( self, "Ä");
  847.         str = ftos( self.ammo_cells1 );
  848.             sprint( self, str );
  849.             sprint( self, "/");
  850.         str = ftos( self.ammo_plasma );
  851.             sprint( self, str );
  852.  
  853.         // armor                                  1234 : 33 left
  854.         if      (self.armortype > 0.78) {str = "\nâââ "; cap = 200;}
  855.         else if (self.armortype > 0.58) {str = "\nââ  "; cap = 150;}
  856.         else if (self.armortype > 0.28) {str = "\nâ   "; cap = 100;}
  857.         else                            {str = "\n    "; cap = 0;}
  858.         sprint( self, str );
  859.  
  860.         if (cap > 0.5)
  861.         {
  862.             c_inc = cap * 0.0303;
  863.             c = c_inc;
  864.             sprint( self, "¥" );
  865.             c2 = 0;
  866.             while (c2 < 32)
  867.             {
  868.                 c = c + c_inc;
  869.                 if (c < self.armorvalue)
  870.                 {
  871.                     if (c > (cap - c_inc) )
  872.                         sprint( self, "ƒ" );
  873.                     else
  874.                         sprint( self, "₧" );
  875.                 }
  876.                 c2 = c2 + 1;
  877.             }
  878.  
  879.         }
  880.  
  881.         sprint( self, "\n" );
  882.     }
  883.     else // automatic health print
  884.     {
  885.         cap = self.dest1_x;
  886.         self.dest1_x = self.health;
  887.  
  888.         // don't print health rots
  889.         if (self.health > 100.5 && cap == self.health + 1) return;
  890.  
  891.         sprint( self, "\n\n" );
  892.     }
  893.  
  894.     c = 2.777;
  895.     cap = self.health;
  896.     if (cap > 100 - c ) cap = 100 - c;
  897.  
  898.     sprint( self, "Ç" );
  899.     while (c < cap)
  900.     {
  901.         sprint( self, "ü" );
  902.         c = c + 2.777;
  903.     }
  904.     if (self.health > 99.5)
  905.         sprint( self, "é" );
  906.  
  907.     if (opt == 1)
  908.     {
  909.         if (self.items & IT_KEY1) sprint( self, "\nS" );
  910.         else                      sprint( self, "\n " );
  911.         if (self.items & IT_KEY2) sprint( self, "G" );
  912.         else                      sprint( self, " " );
  913.  
  914.  
  915.         if ( (self.dest2_x & CHSCAM_ON) )
  916.         {
  917.                   if (self.weapon == IT_SHOTGUN)                    str = "   Shotgun    ";
  918.             else if (self.weapon == IT_SUPER_SHOTGUN)         str = "   Dbl Brl    ";
  919.             else if (self.weapon == IT_NAILGUN)                 str = "   Nailgun    ";
  920.             else if (self.weapon == IT_LAVA_NAILGUN)            str = "   Lava Nails ";
  921.             else if (self.weapon == IT_SUPER_NAILGUN)         str = "   SupNG      ";
  922.             else if (self.weapon == IT_LAVA_SUPER_NAILGUN)    str = "   Lava SupNG ";
  923.             else if (self.weapon == IT_GRENADE_LAUNCHER)        str = "   Grenades   ";
  924.             else if (self.weapon == IT_MULTI_GRENADE)            str = "   Multi Grnds";
  925.             else if (self.weapon == IT_ROCKET_LAUNCHER)         str = "   Rockets    ";
  926.             else if (self.weapon == IT_MULTI_ROCKET)             str = "   Multi Rckts";
  927.             else if (self.weapon == IT_LIGHTNING)                str = "   Lghtng Gun ";
  928.             else if (self.weapon == IT_PLASMA_GUN)                str = "   Plasma Gun ";
  929.             else //(self.weapon == IT_AXE)
  930.                                                                             str = "   Axe        ";
  931.         }
  932.         else                                                                str = "              ";
  933.  
  934.         sprint( self, str );
  935.  
  936.     }
  937.     else
  938.         sprint( self, "\n                " );
  939.  
  940.  
  941.     if (self.health < 100.5)
  942.         sprint( self, "\n" );
  943.     else
  944.     {
  945.                         // kkwwwwwwwwwwwwww
  946.                       //  123456789.123456789.123456789.1234567
  947.         sprint( self,                 "               " );
  948.         c = 225;
  949.         while (c > 99) // 225 200 175 150 125 100
  950.         {
  951.             if (self.health > c)
  952.                 sprint( self, "Ä" );
  953.             else
  954.                 sprint( self, " " );
  955.             c = c - 25;
  956.         }
  957.         sprint( self, "\n" );
  958.     }
  959.  
  960. };
  961.  
  962. // ### HUD mod ###
  963. // ###############
  964.  
  965.  
  966.  
  967.  
  968.  
  969. /*
  970.  #####################
  971.  ### Multiskin Pro ###
  972.  
  973.  player.dest1_y   holds real current skin at all times
  974.                         (for powerup changes to use when switching back)
  975.  
  976.  Orig. functions modifyed:
  977.     WEAPONS.QC
  978.         ImpulseCommands
  979.     CLIENT.QC
  980.         PutClientInServer
  981.  
  982. */
  983.  
  984. // opt:
  985. // 0 = up
  986. // 1 = down
  987. void( float opt ) Choose_multiskin =
  988. {
  989.     local string str;
  990.  
  991.     if (opt == 0)
  992.     {
  993.         self.dest1_y = self.dest1_y + 1;
  994.         if (self.dest1_y > 20)
  995.             self.dest1_y = 0;
  996.     }
  997.     else
  998.     {
  999.         self.dest1_y = self.dest1_y - 1;
  1000.         if (self.dest1_y < 0)
  1001.             self.dest1_y = 20;
  1002.     }
  1003.  
  1004.     self.skin = self.dest1_y;
  1005.  
  1006.     str = ftos( self.skin);
  1007.     sprint( self, "Skin ");
  1008.     sprint( self, str);
  1009.     sprint( self, "\n");
  1010.  
  1011. };
  1012.  
  1013. // ### Multiskin Pro ###
  1014. // #####################
  1015.  
  1016. /*
  1017.  #######################
  1018.  ### Hot Key Weapons ###
  1019.  
  1020.  player.dest_x : holds previous weapon
  1021.  player.dest_y : HK mode; 0=normal (default), 1=multi-explosives
  1022.  player.dest_z : flag for previous weapon switch to continue
  1023.  
  1024.  Rob Albin, Oct 7 96
  1025.  
  1026.  Orig. functions modifyed:
  1027.     WEAPONS.QC
  1028.         ImpulseCommands
  1029.  
  1030.  Abstract:
  1031.     Provides hot-key impulses for axe, grenade, and rocket launcher
  1032.     that return to previous weapon.
  1033.     New cycle weapons impulses that don't select these weapons.
  1034.  
  1035.     uses free player entity variable (float point of vector) dest_x
  1036.     (only used for doors)
  1037.  
  1038.  
  1039.  CFG file use:
  1040.  
  1041.  alias +axe_hotkey "impulse 41; +attack"
  1042.  alias -axe_hotkey "impulse 40; -attack"
  1043.  
  1044.  alias +grenade_hotkey "impulse 42; +attack"
  1045.  alias -grenade_hotkey "impulse 40; -attack"
  1046.  
  1047.  alias +rocket_hotkey "impulse 43; +attack"
  1048.  alias -rocket_hotkey "impulse 40; -attack"
  1049.  
  1050.  bind "<key>" "+axe_hotkey"
  1051.  bind "<key>" "+grenade_hotkey"
  1052.  bind "<key>" "+rocket_hotkey"
  1053.  
  1054.  // new weapons cycle commands (skips hot-key weapons)
  1055.  bind "<key>" "impulse 44"
  1056.  bind "<key>" "impulse 45"
  1057.  
  1058. */
  1059.  
  1060. //    .v_angle_x:
  1061. //        78.8 (max down aim)
  1062. //        -68.9 (max up aim)
  1063.  
  1064. // opt:
  1065. // 1 = axe
  1066. // 2 = grenade launcher
  1067. // 3 = rocket launcher
  1068. void( float opt ) HotKey_weapon =
  1069. {
  1070.     local float w, flg;
  1071.  
  1072.     // save previous weapon
  1073.     // avoid multiple key presses setting previous weapon to
  1074.     // a HK weapon
  1075.     if (self.weapon != IT_GRENADE_LAUNCHER &&
  1076.          self.weapon != IT_ROCKET_LAUNCHER  &&
  1077.          self.weapon != IT_MULTI_GRENADE  &&
  1078.          self.weapon != IT_MULTI_ROCKET  &&
  1079.          self.weapon != IT_AXE)
  1080.         self.dest_x = self.weapon;
  1081.  
  1082.     flg = TRUE;
  1083.  
  1084.     if (opt == 1)
  1085.     {  if (self.v_angle_x > 77)
  1086.         {
  1087.             self.dest_y = 0;
  1088.             centerprint( self, "HK weap: normal explosives");
  1089.         }
  1090.         else if (self.v_angle_x < -67)
  1091.         {
  1092.             self.dest_y = 1;
  1093.             centerprint( self, "HK weap: multi explosives");
  1094.         }
  1095.         w = IT_AXE;
  1096.     }
  1097.     else if (opt == 2)
  1098.     {
  1099.         if (self.dest_y)
  1100.         {
  1101.             if ((self.items & IT_MULTI_GRENADE) &&
  1102.                   self.ammo_multi_rockets > 0)
  1103.                 w = IT_MULTI_GRENADE;
  1104.             else
  1105.                 flg = FALSE;
  1106.         }
  1107.         else
  1108.         {
  1109.             if ((self.items & IT_GRENADE_LAUNCHER) &&
  1110.                   self.ammo_rockets1 > 0)
  1111.                 w = IT_GRENADE_LAUNCHER;
  1112.             else
  1113.                 flg = FALSE;
  1114.         }
  1115.     }
  1116.     else
  1117.     {
  1118.         if (self.dest_y)
  1119.         {
  1120.             if ((self.items & IT_MULTI_ROCKET) &&
  1121.                   self.ammo_multi_rockets > 0)
  1122.                 w = IT_MULTI_ROCKET;
  1123.             else
  1124.                 flg = FALSE;
  1125.         }
  1126.         else
  1127.         {
  1128.             if ((self.items & IT_ROCKET_LAUNCHER) &&
  1129.                   self.ammo_rockets1 > 0)
  1130.                 w = IT_ROCKET_LAUNCHER;
  1131.             else
  1132.                 flg = FALSE;
  1133.         }
  1134.     }
  1135.  
  1136.     if (flg)
  1137.     {
  1138.         self.weapon = w;
  1139.         W_SetCurrentAmmo();
  1140.         stuffcmd( self, "+attack\n");
  1141.         self.dest_z = TRUE; // flag HK switch happened
  1142.     }
  1143.     else
  1144.         sprint( self, "no weapon/ammo\n");
  1145. };
  1146.  
  1147. void() HotKey_previous_weapon =
  1148. {
  1149.     if (! self.dest_z)
  1150.         return;
  1151.  
  1152.     if (self.dest_x)
  1153.     {
  1154.         self.weapon = self.dest_x;
  1155.         W_SetCurrentAmmo();
  1156.     }
  1157.  
  1158.     self.dest_z = FALSE; // reset switch flag
  1159. };
  1160.  
  1161. void() HotKey_CycleWeaponCommand =
  1162. {
  1163.     local float w, it, am, c;
  1164.  
  1165.     c = 0;
  1166.     w = self.weapon;
  1167.  
  1168.     it = self.items;
  1169.     self.impulse = 0;
  1170.  
  1171.     while (1)
  1172.     {
  1173.         am = 0;
  1174.  
  1175.         if (w == IT_AXE)
  1176.         {  w = IT_SHOTGUN;
  1177.             if (self.ammo_shells1 < 1) am = 1;
  1178.         }
  1179.         else if (w == IT_SHOTGUN)
  1180.         {  w = IT_SUPER_SHOTGUN;
  1181.             if (self.ammo_shells1 < 2) am = 1;
  1182.         }
  1183.         else if (w == IT_SUPER_SHOTGUN)
  1184.         {  w = IT_NAILGUN;
  1185.             if (self.ammo_nails1 < 1) am = 1;
  1186.         }
  1187.  
  1188.         else if (w == IT_NAILGUN)
  1189.         {  w = IT_LAVA_NAILGUN;
  1190.             if (self.ammo_lava_nails < 1) am = 1;
  1191.         }
  1192.         else if (w == IT_LAVA_NAILGUN)
  1193.         {  w = IT_SUPER_NAILGUN;
  1194.             if (self.ammo_nails1 < 2) am = 1;
  1195.         }
  1196.  
  1197.         else if (w == IT_SUPER_NAILGUN)
  1198.         {  w = IT_LAVA_SUPER_NAILGUN;
  1199.             if (self.ammo_lava_nails < 2) am = 1;
  1200.         }
  1201.         else if (w == IT_LAVA_SUPER_NAILGUN)
  1202.         {  w = IT_LIGHTNING;
  1203.             if (self.ammo_cells1 < 1) am = 1;
  1204.         }
  1205.  
  1206.         else if (w == IT_GRENADE_LAUNCHER)
  1207.         {  w = IT_LIGHTNING;
  1208.             if (self.ammo_cells1 < 1) am = 1;
  1209.         }
  1210.         else if (w == IT_MULTI_GRENADE)
  1211.         {  w = IT_LIGHTNING;
  1212.             if (self.ammo_cells1 < 1) am = 1;
  1213.         }
  1214.  
  1215.         else if (w == IT_ROCKET_LAUNCHER)
  1216.         {  w = IT_LIGHTNING;
  1217.             if (self.ammo_cells1 < 1) am = 1;
  1218.         }
  1219.         else if (w == IT_MULTI_ROCKET)
  1220.         {  w = IT_LIGHTNING;
  1221.             if (self.ammo_cells1 < 1) am = 1;
  1222.         }
  1223.  
  1224.  
  1225.         else if (w == IT_LIGHTNING)
  1226.         {  w = IT_PLASMA_GUN;
  1227.             if (self.ammo_plasma < 1) am = 1;
  1228.         }
  1229.         else if (w == IT_PLASMA_GUN)
  1230.         {  w = IT_SHOTGUN;
  1231.             if (self.ammo_shells1 < 1) am = 1;
  1232.         }
  1233.  
  1234.         if ( (it & w) && am == 0)
  1235.         {
  1236.             self.weapon = w;
  1237.             W_SetCurrentAmmo ();
  1238.             return;
  1239.         }
  1240.  
  1241.         if (c > 14) return;
  1242.         c = c + 1;
  1243.     }
  1244.  
  1245. };
  1246.  
  1247.  
  1248. void() HotKey_CycleWeaponReverseCommand =
  1249. {
  1250.     local float w, it, am, c;
  1251.  
  1252.     c = 0;
  1253.     w = self.weapon;
  1254.  
  1255.     it = self.items;
  1256.     self.impulse = 0;
  1257.  
  1258.     while (1)
  1259.     {
  1260.         am = 0;
  1261.  
  1262.         if (w == IT_PLASMA_GUN)
  1263.         {    w = IT_LIGHTNING;
  1264.             if (self.ammo_cells1 < 1) am = 1;
  1265.         }
  1266.         else if (w == IT_LIGHTNING)
  1267.         {    w = IT_LAVA_SUPER_NAILGUN;
  1268.             if (self.ammo_lava_nails < 2) am = 1;
  1269.         }
  1270.  
  1271.         else if (w == IT_MULTI_ROCKET)
  1272.         {    w = IT_LAVA_SUPER_NAILGUN;
  1273.             if (self.ammo_lava_nails < 2) am = 1;
  1274.         }
  1275.         else if (w == IT_ROCKET_LAUNCHER)
  1276.         {    w = IT_LAVA_SUPER_NAILGUN;
  1277.             if (self.ammo_lava_nails < 2) am = 1;
  1278.         }
  1279.  
  1280.         else if (w == IT_MULTI_GRENADE)
  1281.         {    w = IT_LAVA_SUPER_NAILGUN;
  1282.             if (self.ammo_lava_nails < 2) am = 1;
  1283.         }
  1284.         else if (w == IT_GRENADE_LAUNCHER)
  1285.         {    w = IT_LAVA_SUPER_NAILGUN;
  1286.             if (self.ammo_lava_nails < 2) am = 1;
  1287.         }
  1288.  
  1289.         else if (w == IT_LAVA_SUPER_NAILGUN)
  1290.         {    w = IT_SUPER_NAILGUN;
  1291.             if (self.ammo_nails1 < 2) am = 1;
  1292.         }
  1293.         else if (w == IT_SUPER_NAILGUN)
  1294.         {    w = IT_LAVA_NAILGUN;
  1295.             if (self.ammo_lava_nails < 1) am = 1;
  1296.         }
  1297.  
  1298.         else if (w == IT_LAVA_NAILGUN)
  1299.         {    w = IT_NAILGUN;
  1300.             if (self.ammo_nails1 < 1) am = 1;
  1301.         }
  1302.         else if (w == IT_NAILGUN)
  1303.         {    w = IT_SUPER_SHOTGUN;
  1304.             if (self.ammo_shells1 < 2) am = 1;
  1305.         }
  1306.  
  1307.         else if (w == IT_SUPER_SHOTGUN)
  1308.         {    w = IT_SHOTGUN;
  1309.             if (self.ammo_shells1 < 1) am = 1;
  1310.         }
  1311.         else if (w == IT_SHOTGUN)
  1312.         {  w = IT_PLASMA_GUN;
  1313.             if (self.ammo_plasma < 1) am = 1;
  1314.         }
  1315.         else if (w == IT_AXE)
  1316.         {  w = IT_PLASMA_GUN;
  1317.             if (self.ammo_plasma < 1) am = 1;
  1318.         }
  1319.  
  1320.         if ( (it & w) && am == 0)
  1321.         {
  1322.             self.weapon = w;
  1323.             W_SetCurrentAmmo ();
  1324.             return;
  1325.         }
  1326.  
  1327.         if (c > 14) return;
  1328.         c = c + 1;
  1329.     }
  1330.  
  1331. };
  1332.  
  1333. // ### Hot Key Weapons mod ###
  1334. // ###########################
  1335.  
  1336.  
  1337. // #########################
  1338. // ### Start.bsp Marquee ###
  1339.  
  1340. void () S_E_CLVLS_marquee =
  1341. {
  1342.     self.nextthink = time + 1;
  1343.     self.ammo_shells = self.ammo_shells + 1;
  1344.     centerprint( self.owner, "¡ ├Φß≤σπßφ ╔╔ QuakeC mod ¡\n\n¡  written by Rob Albin  ¡" );
  1345.     if (self.ammo_shells > 3)
  1346.         remove( self );
  1347. };
  1348.  
  1349. // float S_E_CLVLS_flag;
  1350. void () Spawn_extra_changelevels =
  1351. {
  1352.     local float i;
  1353.     local entity e;
  1354.  
  1355.     if (time < 5)
  1356.     {
  1357.         e = spawn();
  1358.         e.owner = self.owner;
  1359.         e.nextthink = time + 3;
  1360.         e.think = S_E_CLVLS_marquee;
  1361.     }
  1362.  
  1363. };
  1364.  
  1365. // ### Start.bsp Marquee ###
  1366. // #########################
  1367.  
  1368.  
  1369. // #####################################
  1370. // ### Single Player Alternate Rules ###
  1371.  
  1372.     //altrules_itemremove( "weapon_supershotgun" );
  1373.     //altrules_itemremove( "weapon_nailgun" );
  1374.     //altrules_itemremove( "weapon_supernailgun" );
  1375.     //altrules_itemremove( "weapon_grenadelauncher" );
  1376.     //altrules_itemremove( "weapon_rocketlauncher" );
  1377.     //altrules_itemremove( "weapon_lightning" );
  1378.     //altrules_itemremove( "item_shells" );
  1379.     //altrules_itemremove( "item_spikes" );
  1380.     //altrules_itemremove( "item_rockets" );
  1381.     //altrules_itemremove( "item_cells" );
  1382.  
  1383. void( string n ) altrules_itemremove =
  1384. {
  1385.     local entity ent, t_ent;
  1386.  
  1387.     ent = find (world, classname, n);
  1388.     while (ent)
  1389.     {
  1390.         t_ent = find (ent, classname, n);
  1391.         // leave any with .target/.killtarget names
  1392.         if (ent.target == "" && ent.killtarget == "")
  1393.             remove( ent );
  1394.         else
  1395.         {
  1396.             ent.health = 1;
  1397.             ent.max_health = 1;
  1398.         }
  1399.         ent = t_ent;
  1400.     }
  1401. };
  1402.  
  1403. // ### Items2 Rules ###
  1404.  
  1405. void () items2_levelstart_think =
  1406. {
  1407.     local    entity ent;
  1408.     local    float num_b, total_h, avg_h;
  1409.     //local string s;
  1410.  
  1411.     num_b = 0;
  1412.     total_h = 0;
  1413.  
  1414.     // get total boxes and health in world
  1415.     ent = find (world, classname, "item_health");
  1416.     while (ent)
  1417.     {
  1418.         if (!(ent.spawnflags & H_MEGA))
  1419.         {
  1420.             num_b = num_b + 1;
  1421.             total_h = total_h + ent.max_health;
  1422.         }
  1423.         ent = find (ent, classname, "item_health");
  1424.     }
  1425.  
  1426.     if (num_b < 2)
  1427.         return;
  1428.     avg_h = rint(total_h / num_b);
  1429.  
  1430.     // reset boxes for items2 rules
  1431.     ent = find (world, classname, "item_health");
  1432.     while (ent)
  1433.     {
  1434.         if (!(ent.spawnflags & H_MEGA))
  1435.         {
  1436.             ent.health = avg_h;
  1437.             ent.max_health = avg_h;
  1438.             setmodel(ent, "maps/b_bh25.bsp");
  1439.             ent.noise = "items/health1.wav";
  1440.         }
  1441.         ent = find (ent, classname, "item_health");
  1442.     }
  1443.  
  1444.     //s = ftos(num_b);
  1445.     //bprint("Total boxes = ");
  1446.     //bprint(s);
  1447.  
  1448.     //s = ftos(total_h);
  1449.     //bprint("\nTotal health points = ");
  1450.     //bprint(s);
  1451.  
  1452.     //s = ftos(avg_h);
  1453.     //bprint("\nAvg. health points = ");
  1454.     //bprint(s);
  1455.  
  1456.     //bprint("\n");
  1457.  
  1458.     bprint( "Items2 rules on\n" );
  1459.     remove( self );
  1460. };
  1461.  
  1462. void () items2_levelstart =
  1463. {
  1464.     local entity ent;
  1465.  
  1466.     ent = spawn();
  1467.     ent.nextthink = time + 1;
  1468.     ent.think = items2_levelstart_think;
  1469. };
  1470.  
  1471.  
  1472. // ### Vampire Rules ###
  1473. /*
  1474.  
  1475. entity player_ent; // ruins coop
  1476.  
  1477. float MAX_HEALTH_MULT = 2.5;  // multiplyer for .max_health for monsters
  1478.                                         // also used to divide back down for normal health
  1479.                                         // when player kills a monster
  1480.  
  1481. // called by T_Damage() in vampire rules, conditions coming in:
  1482. // -both targ and att(acker) are player or monster
  1483. // -take has just been subtracted from targ.health
  1484. void( entity targ, entity attacker, float take ) vamp_checkdamage =
  1485. {
  1486.     local float d;
  1487.     local entity att;
  1488.  
  1489.     att = attacker; // just to make sure, not sure on by value/ref. in QC
  1490.  
  1491.     if (targ == att)
  1492.             return;
  1493.  
  1494.     if ((att.flags & FL_CLIENT) ||
  1495.           !(att.flags & FL_MONSTER))
  1496.     {
  1497.         // set to player if client or something in world killed targ
  1498.         att = player_ent;
  1499.         if(targ.health < 1)
  1500.             d = rint((targ.max_health / MAX_HEALTH_MULT) * 0.1);
  1501.         else
  1502.             return;
  1503.     }
  1504.     else
  1505.     {
  1506.         if (targ.health < 0)
  1507.             // subtract off damage past 0
  1508.             d = take + targ.health;
  1509.         else
  1510.             d = take;
  1511.         if ((targ.flags & FL_CLIENT))
  1512.             d = take * 2;
  1513.     }
  1514.  
  1515.     att.health = att.health + d;
  1516.     if (att.health > att.max_health)
  1517.         att.health = att.max_health;
  1518. };
  1519.  
  1520. void() vamp_levelstart_think =
  1521. {
  1522.     local    entity ent;
  1523.     //local string s;
  1524.  
  1525.     altrules_itemremove( "item_health" );
  1526.  
  1527.     // set player and monsters .max_health for vampire rules
  1528.     ent = nextent(world);
  1529.     while (ent != world)
  1530.     {
  1531.         if ((ent.flags & FL_MONSTER))
  1532.             ent.max_health = ent.health * 2.5;
  1533.         else if ((ent.flags & FL_CLIENT))
  1534.         {
  1535.             ent.max_health = 150;
  1536.             player_ent = ent;
  1537.         }
  1538.  
  1539.         ent = nextent(ent);
  1540.     }
  1541.  
  1542.     bprint( "Vampire rules on\n" );
  1543.     remove( self );
  1544. };
  1545. */
  1546.  
  1547. void () vamp_levelstart =
  1548. {
  1549.     //local entity ent;
  1550.  
  1551.     //ent = spawn();
  1552.     //ent.nextthink = time + 1;
  1553.     //ent.think = vamp_levelstart_think;
  1554. };
  1555.  
  1556. // ### Single Player Alternate Rules ###
  1557. // #####################################
  1558.  
  1559.